tower-http 0.2.5

Tower middleware and utilities for HTTP clients and servers
Documentation
`async fn(HttpRequest) -> Result` # Overview tower-http is a library that provides HTTP-specific middleware and utilities built on top of [tower]. All middleware uses the [http] and [http-body] crates as the HTTP abstractions. That means they're compatible with any library or framework that also uses those crates, such as [hyper], [tonic], and [warp]. # Example server This example shows how to apply middleware from tower-http to a [`Service`] and then run that service using [hyper]. ```rust,no_run use tower_http::{ add_extension::AddExtensionLayer, compression::CompressionLayer, propagate_header::PropagateHeaderLayer, auth::RequireAuthorizationLayer, sensitive_headers::SetSensitiveRequestHeadersLayer, set_header::SetResponseHeaderLayer, trace::TraceLayer, }; use tower::{ServiceBuilder, service_fn, make::Shared}; use http::{Request, Response, header::{HeaderName, CONTENT_TYPE, AUTHORIZATION}}; use hyper::{Body, Error, server::Server, service::make_service_fn}; use std::{sync::Arc, net::SocketAddr, convert::Infallible, iter::once}; # struct DatabaseConnectionPool; # impl DatabaseConnectionPool { # fn new() -> DatabaseConnectionPool { DatabaseConnectionPool } # } # fn content_length_from_response(_: &http::Response) -> Option { None } # async fn update_in_flight_requests_metric(count: usize) {} // Our request handler. This is where we would implement the application logic // for responding to HTTP requests... async fn handler(request: Request) -> Result, Error> { // ... # todo!() } // Shared state across all request handlers --- in this case, a pool of database connections. struct State { pool: DatabaseConnectionPool, } #[tokio::main] async fn main() { // Construct the shared state. let state = State { pool: DatabaseConnectionPool::new(), }; // Use tower's `ServiceBuilder` API to build a stack of tower middleware // wrapping our request handler. let service = ServiceBuilder::new() // Mark the `Authorization` request header as sensitive so it doesn't show in logs .layer(SetSensitiveRequestHeadersLayer::new(once(AUTHORIZATION))) // High level logging of requests and responses .layer(TraceLayer::new_for_http()) // Share an `Arc` with all requests .layer(AddExtensionLayer::new(Arc::new(state))) // Compress responses .layer(CompressionLayer::new()) // Propagate `X-Request-Id`s from requests to responses .layer(PropagateHeaderLayer::new(HeaderName::from_static("x-request-id"))) // If the response has a known size set the `Content-Length` header .layer(SetResponseHeaderLayer::overriding(CONTENT_TYPE, content_length_from_response)) // Authorize requests using a token .layer(RequireAuthorizationLayer::bearer("passwordlol")) // Wrap a `Service` in our middleware stack .service_fn(handler); // And run our service using `hyper` let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); Server::bind(&addr) .serve(Shared::new(service)) .await .expect("server error"); } ``` Keep in mind that while this example uses [hyper], tower-http supports any HTTP client/server implementation that uses the [http] and [http-body] crates. # Example client tower-http middleware can also be applied to HTTP clients: ```rust,no_run use tower_http::{ decompression::DecompressionLayer, set_header::SetRequestHeaderLayer, trace::TraceLayer, classify::StatusInRangeAsFailures, }; use tower::{ServiceBuilder, Service, ServiceExt}; use hyper::Body; use http::{Request, HeaderValue, header::USER_AGENT}; #[tokio::main] async fn main() { let mut client = ServiceBuilder::new() // Add tracing and consider server errors and client // errors as failures. .layer(TraceLayer::new( StatusInRangeAsFailures::new(400..=599).into_make_classifier() )) // Set a `User-Agent` header on all requests. .layer(SetRequestHeaderLayer::overriding( USER_AGENT, HeaderValue::from_static("tower-http demo") )) // Decompress response bodies .layer(DecompressionLayer::new()) // Wrap a `hyper::Client` in our middleware stack. // This is possible because `hyper::Client` implements // `tower::Service`. .service(hyper::Client::new()); // Make a request let request = Request::builder() .uri("http://example.com") .body(Body::empty()) .unwrap(); let response = client .ready() .await .unwrap() .call(request) .await .unwrap(); } ``` # Feature Flags All middleware are disabled by default and can be enabled using [cargo features]. For example, to enable the [`Trace`] middleware, add the "trace" feature flag in your `Cargo.toml`: ```toml tower-http = { version = "0.1", features = ["trace"] } ``` You can use `"full"` to enable everything: ```toml tower-http = { version = "0.1", features = ["full"] } ``` # Getting Help If you're new to tower its [guides] might help. In the tower-http repo we also have a [number of examples][examples] showing how to put everything together. You're also welcome to ask in the [`#tower` Discord channel][chat] or open an [issue] with your question. [tower]: https://crates.io/crates/tower [http]: https://crates.io/crates/http [http-body]: https://crates.io/crates/http-body [hyper]: https://crates.io/crates/hyper [guides]: https://github.com/tower-rs/tower/tree/master/guides [tonic]: https://crates.io/crates/tonic [warp]: https://crates.io/crates/warp [cargo features]: https://doc.rust-lang.org/cargo/reference/features.html [`AddExtension`]: crate::add_extension::AddExtension [`Service`]: https://docs.rs/tower/latest/tower/trait.Service.html [chat]: https://discord.gg/tokio [issue]: https://github.com/tower-rs/tower-http/issues/new [`Trace`]: crate::trace::Trace [examples]: https://github.com/tower-rs/tower-http/tree/master/examples